#include "StdAfx.h"
#include "GeneticProcess.h"
#include <list>
#include <iostream>

GeneticProcess::GeneticProcess(unsigned int populationCount, unsigned int mutationPercent, unsigned int crosoverPercent, ISpecimenFactory *specimenFactory, Random *generator)
	:m_populationCount(populationCount),
	 m_mutationPercent(mutationPercent), 
	 m_crosoverPercent(crosoverPercent),
	 m_specimenFactory(specimenFactory),
	 m_generator(generator)
{
	m_population = new std::list<ISpecimen*>();
}

GeneticProcess::~GeneticProcess(void)
{
}

void GeneticProcess::Initialize()
{
	unsigned int initial_population = 2 * m_populationCount;
	for(unsigned int i = 0; i < initial_population; i++)
	{
		m_population->push_back(m_specimenFactory->CreateSpecimen());
	}
}

bool GeneticProcess::sortPredicate(ISpecimen* lhs, ISpecimen* rhs)
{
	//std::cout << "******************* " << lhs->ToString() << std::endl;
	return *lhs < *rhs;
}
void GeneticProcess::Select()
{
//	std::cout << "size before select: " << m_population->size() << std::endl;
	m_population->sort(sortPredicate);
	/* todo: delete unwanted triangles */
	std::list<ISpecimen*>::iterator iter;
	unsigned int tmp_cnt = 1;
	for(iter = m_population->begin(); iter != m_population->end(); iter++)
	{
		if(tmp_cnt > m_populationCount)
		{
			delete (*iter);
		}
	}
	m_population->resize(m_populationCount);
//	std::cout << "size after select: " << m_population->size() << std::endl;
//	std::cout << this->ToString() << std::endl;
}

void GeneticProcess::Mutate()
{
	std::list<ISpecimen*>::iterator iter;
	std::list<ISpecimen*>::iterator end = m_population->end();

	std::list<ISpecimen*> mutants;

	for(iter = m_population->begin(); iter != m_population->end(); iter++)
	{
		if(m_generator->GetNumber(100) <= m_mutationPercent)
			mutants.push_back((*iter)->Mutate());
	}
	mutants.sort();
	m_population->sort();
	m_population->merge(mutants);
}

void GeneticProcess::Crosover()
{
	std::list<ISpecimen*>::iterator father;
	std::list<ISpecimen*>::iterator end = m_population->end();
	std::list<ISpecimen*> tmp;
	/* find father */
	for(father = m_population->begin(); father != end; father++)
	{
		if(m_generator->GetNumber(100) <= m_crosoverPercent)
		{
			/* find mother */
			std::list<ISpecimen*>::iterator mother;
			for(mother = m_population->begin(); mother != end; mother++)
			{
				if(m_generator->GetNumber(100) <= m_crosoverPercent)
				{
					tmp.push_back((*father)->Crossover(*mother));
				}
			}
		}
	}
	tmp.sort();
	m_population->sort();
	m_population->merge(tmp);
}

std::string GeneticProcess::ToString()
{
	std::string s;
	std::list<ISpecimen*>::iterator iter;
//todo: string
	for(iter = m_population->begin(); iter != m_population->end(); iter++)
	{
		s += (*iter)->ToString();
		s += "\n";
	}
	return s;
}

std:: string GeneticProcess::GetBest(unsigned int max_cnt)
{
	max_cnt = max_cnt < m_populationCount ? max_cnt : m_populationCount;
	std::string s;
	std::list<ISpecimen*>::iterator iter;

	for(iter = m_population->begin(); iter != m_population->end(); iter++)
	{
		if(max_cnt == 0)
			break;
		s += (*iter)->ToString();
		s += "\n";
		max_cnt--;
	}
	return s;

}


void GeneticProcess::debug(std::string txt)
{
	std::cout << txt << std::endl;
}
